package org.mayanjun.code.easyweb.springmvc.handler;

import org.apache.commons.lang.StringUtils;
import org.mayanjun.code.easyweb.common.Result;
import org.mayanjun.code.easyweb.common.ServiceException;
import org.mayanjun.code.easyweb.common.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

/**
 * Handle some exception
 * @author mayanjun
 * @since 1.0.1
 */
public class ApplicationExceptionHandler {
	
	private static final Logger LOG = LoggerFactory.getLogger(ApplicationExceptionHandler.class);

	private static final String SERVICE_EXCEPTION_CLASSNAME = ServiceException.class.getName();
    
    public static Result handleAllException(Throwable t) {
    	if(t instanceof ServiceException) {
    		return handleInternalServiceException(t);
		} else if(t instanceof MethodArgumentTypeMismatchException) {
			String name = ((MethodArgumentTypeMismatchException) t).getName();
			return new Result(new CustomStatus(Status.PARAM_MISS.getCode(), "参数错误:" + name));
		} else if(t instanceof MissingServletRequestParameterException) {
			String paramName = ((MissingServletRequestParameterException) t).getParameterName();
			return new Result(new CustomStatus(Status.PARAM_MISS.getCode(), "缺少参数" + paramName));
		} else if(t instanceof RuntimeException) {
			return handleSCFServiceException(t);
		} else {
			return handleUnknownException(t);
		}
    }

	private static Result handleInternalServiceException(Throwable t) {
		ServiceException st = (ServiceException)t;
		LOG.info("Service Exception Detected: {}", st.getMessage());
		Result re = new Result(((ServiceException) t).getStatus());

		if(((ServiceException) t).getHolder() != null) re.getData().putAll(((ServiceException) t).getHolder());
		return re;
	}

	private static Result handleSCFServiceException(Throwable t) {
		String message = t.getMessage();
		StringBuffer sb = new StringBuffer();
		if(!StringUtils.isBlank(message)) {
			for(int i = 0; i < message.length(); i++) {
				char c = message.charAt(i);
				if(c == '\r' || c == '\n') break;
				sb.append(c);
			}
			String head = sb.toString();
			if(!StringUtils.isBlank(head) && head.startsWith(SERVICE_EXCEPTION_CLASSNAME)) {
				String msg = head.substring(head.indexOf(":") + 1);
				if(!StringUtils.isBlank(msg)) msg = msg.trim();
				else msg = "操作失败";
				return handleInternalServiceException(new ServiceException(Status.INTERNAL_ERROR, msg));
			}
		}
		return handleUnknownException(t);
	}

	private static Result handleUnknownException(Throwable t) {
		LOG.error("Error Detected: {} > {}", t.getClass().getCanonicalName(), t.getMessage(), t);
		return new Result(Status.INTERNAL_ERROR).setException(t.getMessage());
	}

    private static class CustomStatus extends Status {
    	public CustomStatus(int code, String message) {
    		super(code,message);
		}
    }
}